﻿using System;

namespace MyLib.Data {
	/// <summary>
	/// 
	/// </summary>
	public class RunningNumberProvider : DbContextProvider {
		/// <summary>
		/// 
		/// </summary>
		/// <param name="numberType"></param>
		/// <param name="seed"></param>
		/// <param name="inc"></param>
		/// <returns></returns>
		public long Next(int numberType, long seed = 1L, long inc = 1L) {
			var paramNumType = new DbParameter("num_type", DbParameterType.Integer, numberType);
			var paramValue = new DbParameter("value", DbParameterType.Long, 0);

			using (var session = SessionFactory.CreateSession()) {
				var oldNumber = session.ExecuteScalar<string>(
					"select `value` from my_runningnumber where `num_type` = #num_type# for update",
					System.Data.CommandType.Text,
					paramNumType);

				if (string.IsNullOrEmpty(oldNumber)) {
					long newNumber = seed;

					session.ExecuteUpdate(
						"insert into my_runningnumber (`num_type`, `value`) values(#num_type#, #value#)",
						System.Data.CommandType.Text,
						new DbParameter("num_type", DbParameterType.Long, System.Data.ParameterDirection.Input, numberType),
						new DbParameter("value", DbParameterType.Long, System.Data.ParameterDirection.Input, newNumber));

					session.Commit();

					return newNumber;
				} else {
					long newNumber;
					if (!long.TryParse(oldNumber, out newNumber)) {
						newNumber = seed;
					} else {
						newNumber += inc;
					}

					session.ExecuteUpdate(
						"update my_runningnumber set `value` = #value# where `num_type` = #num_type#",
						System.Data.CommandType.Text,
						new DbParameter("num_type", DbParameterType.Long, System.Data.ParameterDirection.Input, numberType),
						new DbParameter("value", DbParameterType.Long, System.Data.ParameterDirection.Input, newNumber));

					session.Commit();

					return newNumber;
				} // end of if.
			} // end of Next.
		}
	} // end of RunningNumberProvider.
}
